package com.gmrz.uaf.servlet.v1.handler;

import com.gmrz.uaf.common.Constants;
import com.gmrz.uaf.common.GuiceUtil;
import com.gmrz.uaf.protocol.v1.json.UAFSchemaBuilder;
import com.gmrz.uaf.protocol.v1.processor.UAFRegStatusProcessor;
import com.gmrz.uaf.server.ServerContext;
import com.gmrz.uaf.servlet.v1.request.ReceiveReqPayload;
import com.gmrz.uaf.servlet.v1.request.RegStatusContext;
import com.gmrz.uaf.servlet.v1.response.FidoRespPayload;
import com.gmrz.uaf.servlet.v1.validation.PayloadValidationException;
import com.gmrz.uaf.servlet.v1.validation.RestValidator;
import com.gmrz.util.Strings;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by chentaikun on 16/12/20.
 */
public class UAFRegStatusHandler extends UAFBaseHandler{

    private static final Logger LOG = LogManager.getLogger(UAFRegStatusHandler.class);
    /**
     * {
     *     "context":{
     *          "transNo":"32characters",
     *          "userName":"user1",
     *          "appID","001",
     *          "transType":["00","01"],
     *          "deviceID":"abcdefg",
     *          "authType":["00","01"]
     *     }
     * }
     * @param request
     * {
     *     "statusCode":1200,
     *     "description":"xxxxxx",
     *     "regStatus":[["1","0"],["0","1"]]//0:未开通,1:开通
     * }
     */
    public String regStatus(String request){

        LOG.info("[/reg/status][begin]");
        ServerContext.getServerContext().getFidoLog().setRequest(request);
        FidoRespPayload<String> respPayload = new FidoRespPayload<String>();
        String response = null;

        try {
            Type reqType = new TypeToken<ReceiveReqPayload<RegStatusContext>>() {  }
                    .getType();

            Gson gson = UAFSchemaBuilder.getGson();
            // 将请求串转为对象
            ReceiveReqPayload<RegStatusContext> reqPayload =gson.fromJson(request, reqType);
            String authType = null;
            if(reqPayload.getContext().getAuthType() != null && reqPayload.getContext().getAuthType().size() > 0){
                authType = reqPayload.getContext().getAuthType().get(0);
            }
            // 日志记录
            logRequest(request,reqPayload.getContext().getTransNo(),reqPayload.getContext().getUserName(),
                    reqPayload.getContext().getAppID(), Strings.listToString(reqPayload.getContext().getAuthType()),null, Constants.Method.REG_STATUS);
            //验证厂商白名单和设备黑名单
            validateDevice(reqPayload.getContext().getDevices(),reqPayload.getContext().getAppID());
            // 兼容 旧接口的deviceID
            if(Strings.isNullOrEmpty(reqPayload.getContext().getDeviceID())){
                reqPayload.getContext().setDeviceID(reqPayload.getContext().getDevices().getDeviceID());
            }
            // 校验请求参数
            validate(reqPayload);

            UAFRegStatusProcessor processor = GuiceUtil.getProcessorInjector().
                    getInstance(UAFRegStatusProcessor.class);
            RegStatusContext context = reqPayload.getContext();
            // hash 用户名
            String userName = generateHashedUserName(context.getUserName(),context.getRf1(),context.getRf2());
            // 查询开通状态
            List<List<String>> regStatus = processor.request(userName
                    ,context.getAppID(),context.getDeviceID(),
                    context.getAuthType(),context.getTransType());
            Map<String,String> exts = new HashMap<String,String>();
            for(String aType : context.getAuthType()){
                // 判断认证方式是否为证书
                if (aType.compareTo(Constants.AuthType.CERT_FINGERPRINT.getAuthType()) >= 0) {
                    // 查询证书的过期时间
                    long afterTime =  processor.getCertAfterDate (userName,  context.getAppID(), context.getDeviceID(), aType, "02");
                    if(afterTime > 0){
                        exts.put(aType,String.valueOf(afterTime));
                    }
                }
            }
            if(!exts.isEmpty()){
                Map<String,String> map = new HashMap<String, String>();
                map.put("certExpireData",gson.toJson(exts));
                respPayload.setExts(map);
            }
            respPayload.setStatusCode(1200);
            respPayload.setDescription("OK");
            respPayload.setRegStatus(regStatus);
            return gson.toJson(respPayload);
        } catch (Exception ex) {
            LOG.error(ex);
            response = buildFidoRespFromException(respPayload, ex);
        }
        LOG.info("[/reg/status][end]");
        return response;

    }

    private void validate(ReceiveReqPayload<RegStatusContext> reqPayload)
            throws PayloadValidationException
    {

        if ((reqPayload == null) || (reqPayload.getContext() == null)) {
            throw new PayloadValidationException("context", RestValidator.VALIDATION_ERROR.EMPTY);
        }
        RegStatusContext context = reqPayload.getContext();
            List<String> authType = context.getAuthType();
            for(String auth:authType){
                RestValidator.validate("authType", auth);
            }

        RestValidator.validate("appID", context.getAppID());
        RestValidator.validate("userName",context.getUserName());
        RestValidator.validate("deviceID",context.getDeviceID());
        RestValidator.validate("transNo", reqPayload.getContext().getTransNo());

        RestValidator.validate("rf1", context.getRf1());
        RestValidator.validate("rf2", context.getRf2());
        RestValidator.validateDevices(context.getDevices());
    }
}
